package cc.uncarbon.module.sys.service;

import cc.uncarbon.framework.core.constant.HelioConstant;
import cc.uncarbon.framework.core.exception.BusinessException;
import cc.uncarbon.framework.core.page.PageParam;
import cc.uncarbon.framework.core.page.PageResult;
import cc.uncarbon.module.sys.entity.VbenMenuEntity;
import cc.uncarbon.module.sys.mapper.VbenMenuMapper;
import cc.uncarbon.module.sys.model.request.AdminVbenMenuInsertOrUpdateDTO;
import cc.uncarbon.module.sys.model.request.AdminVbenMenuListDTO;
import cc.uncarbon.module.sys.model.response.VbenMenuBO;
import cc.uncarbon.module.sys.model.response.VbenMenuSlideBO;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


/**
 * 数据表注释
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class VbenMenuService {

    private final VbenMenuMapper vbenMenuMapper;
    private static final Long ROOT_PARENT_ID = 0L;

    /**
     * 后台管理-分页列表
     */
    public PageResult<VbenMenuBO> adminList(PageParam pageParam, AdminVbenMenuListDTO dto) {
        Page<VbenMenuEntity> entityPage = vbenMenuMapper.selectPage(
                new Page<>(pageParam.getPageNum(), pageParam.getPageSize()),
                new QueryWrapper<VbenMenuEntity>()
                        .lambda()
                        // 名称
                        .like(CharSequenceUtil.isNotBlank(dto.getName()), VbenMenuEntity::getName, CharSequenceUtil.cleanBlank(dto.getName()))
                        // 路由地址
                        .like(CharSequenceUtil.isNotBlank(dto.getPath()), VbenMenuEntity::getPath, CharSequenceUtil.cleanBlank(dto.getPath()))
                        // 重定向路由地址
                        .like(CharSequenceUtil.isNotBlank(dto.getRedirect()), VbenMenuEntity::getRedirect, CharSequenceUtil.cleanBlank(dto.getRedirect()))
                        // 上级菜单ID(根节点设置为0)
                        .eq(Objects.nonNull(dto.getParentId()), VbenMenuEntity::getParentId, dto.getParentId())
                        // 权限标识
                        .like(CharSequenceUtil.isNotBlank(dto.getAuthCode()), VbenMenuEntity::getAuthCode, CharSequenceUtil.cleanBlank(dto.getAuthCode()))
                        // 图标
                        .like(CharSequenceUtil.isNotBlank(dto.getIcon()), VbenMenuEntity::getIcon, CharSequenceUtil.cleanBlank(dto.getIcon()))
                        // 激活图标（菜单）
                        .like(CharSequenceUtil.isNotBlank(dto.getActiveIcon()), VbenMenuEntity::getActiveIcon, CharSequenceUtil.cleanBlank(dto.getActiveIcon()))
                        // 当前路由在菜单中不展现
                        .eq(Objects.nonNull(dto.getHideInMenu()), VbenMenuEntity::getHideInMenu, dto.getHideInMenu())
                        // 当前路由在标签页不展现
                        .eq(Objects.nonNull(dto.getHideinTab()), VbenMenuEntity::getHideinTab, dto.getHideinTab())
                        // 忽略权限，直接可以访问@default false
                        .eq(Objects.nonNull(dto.getIgnoreAccess()), VbenMenuEntity::getIgnoreAccess, dto.getIgnoreAccess())
                        // 开启KeepAlive缓存
                        .eq(Objects.nonNull(dto.getKeepAlive()), VbenMenuEntity::getKeepAlive, dto.getKeepAlive())
                        // 外链-跳转路径
                        .like(CharSequenceUtil.isNotBlank(dto.getLink()), VbenMenuEntity::getLink, CharSequenceUtil.cleanBlank(dto.getLink()))
                        // 在新窗口打开
                        .eq(Objects.nonNull(dto.getOpenInNewWindow()), VbenMenuEntity::getOpenInNewWindow, dto.getOpenInNewWindow())
                        // 用于路由->菜单排序
                        .eq(Objects.nonNull(dto.getSort()), VbenMenuEntity::getSort, dto.getSort())
                        // 标题名称
                        .like(CharSequenceUtil.isNotBlank(dto.getTitle()), VbenMenuEntity::getTitle, CharSequenceUtil.cleanBlank(dto.getTitle()))
                        // 类型
                        .like(CharSequenceUtil.isNotBlank(dto.getType()), VbenMenuEntity::getType, CharSequenceUtil.cleanBlank(dto.getType()))
                        // 页面组件
                        .like(CharSequenceUtil.isNotBlank(dto.getComponent()), VbenMenuEntity::getComponent, CharSequenceUtil.cleanBlank(dto.getComponent()))
                        // 时间区间
                        .between(Objects.nonNull(dto.getBeginAt()) && Objects.nonNull(dto.getEndAt()), VbenMenuEntity::getCreatedAt, dto.getBeginAt(), dto.getEndAt())
                        // 排序
                        .orderByDesc(VbenMenuEntity::getCreatedAt)
        );

        return this.entityPage2BOPage(entityPage);
    }

    /**
     * 根据 ID 取详情
     *
     * @param id 主键ID
     * @return null or BO
     */
    public VbenMenuBO getOneById(Long id) {
        return this.getOneById(id, false);
    }

    /**
     * 根据 ID 取详情
     *
     * @param id               主键ID
     * @param throwIfInvalidId 是否在 ID 无效时抛出异常
     * @return null or BO
     */
    public VbenMenuBO getOneById(Long id, boolean throwIfInvalidId) throws BusinessException {
        VbenMenuEntity entity = vbenMenuMapper.selectById(id);
        if (throwIfInvalidId && entity == null) {
            throw new BusinessException(400, "无效数据表注释ID");
        }

        return this.entity2BO(entity);
    }

    /**
     * 后台管理-新增
     */
    @Transactional(rollbackFor = Exception.class)
    public Long adminInsert(AdminVbenMenuInsertOrUpdateDTO dto) {
        log.info("[后台管理-数据表注释-新增] >> DTO={}", dto);
        this.checkExistence(dto);

        dto.setId(null);
        VbenMenuEntity entity = new VbenMenuEntity();
        BeanUtil.copyProperties(dto, entity);

        vbenMenuMapper.insert(entity);

        return entity.getId();
    }

    /**
     * 后台管理-编辑
     */
    @Transactional(rollbackFor = Exception.class)
    public void adminUpdate(AdminVbenMenuInsertOrUpdateDTO dto) {
        log.info("[后台管理-数据表注释-编辑] >> DTO={}", dto);
        this.checkExistence(dto);

        VbenMenuEntity entity = new VbenMenuEntity();
        BeanUtil.copyProperties(dto, entity);

        vbenMenuMapper.updateById(entity);
    }

    /**
     * 后台管理-删除
     */
    @Transactional(rollbackFor = Exception.class)
    public void adminDelete(Collection<Long> ids) {
        log.info("[后台管理-数据表注释-删除] >> ids={}", ids);
        vbenMenuMapper.deleteByIds(ids);
    }


    /*
    ----------------------------------------------------------------
                        私有方法 private methods
    ----------------------------------------------------------------
     */

    /**
     * 实体转 BO
     *
     * @param entity 实体
     * @return BO
     */
    private VbenMenuBO entity2BO(VbenMenuEntity entity) {
        if (entity == null) {
            return null;
        }

        VbenMenuBO bo = new VbenMenuBO();
        BeanUtil.copyProperties(entity, bo);

        // 可以在此处为BO填充字段

        return bo;
    }

    /**
     * 实体 List 转 BO List
     *
     * @param entityList 实体 List
     * @return BO List
     */
    private List<VbenMenuBO> entityList2BOs(List<VbenMenuEntity> entityList) {
        if (CollUtil.isEmpty(entityList)) {
            return Collections.emptyList();
        }

        // 深拷贝
        List<VbenMenuBO> ret = new ArrayList<>(entityList.size());
        entityList.forEach(
                entity -> ret.add(this.entity2BO(entity))
        );

        return ret;
    }

    /**
     * 实体分页转 BO 分页
     *
     * @param entityPage 实体分页
     * @return BO 分页
     */
    private PageResult<VbenMenuBO> entityPage2BOPage(Page<VbenMenuEntity> entityPage) {
        return new PageResult<VbenMenuBO>()
                .setCurrent(entityPage.getCurrent())
                .setSize(entityPage.getSize())
                .setTotal(entityPage.getTotal())
                .setRecords(this.entityList2BOs(entityPage.getRecords()));
    }

    /**
     * 检查是否已存在同名数据
     *
     * @param dto DTO
     */
    private void checkExistence(AdminVbenMenuInsertOrUpdateDTO dto) {
        /*
        可以根据自己业务需要，解禁这段代码，修改判断条件和文案
*/
        VbenMenuEntity existingEntity = vbenMenuMapper.selectOne(
                new QueryWrapper<VbenMenuEntity>()
                        .lambda()
                        .select(VbenMenuEntity::getId)
                        .eq(VbenMenuEntity::getTitle, dto.getTitle())
                        .last(HelioConstant.CRUD.SQL_LIMIT_1)
        );

        if (existingEntity != null && !existingEntity.getId().equals(dto.getId())) {
            throw new BusinessException(400, "已存在相同数据表注释，请重新输入");
        }

    }

    public List<Map<String, Object>> menus() {
        QueryWrapper<VbenMenuEntity> wrapper = new QueryWrapper<VbenMenuEntity>();
        wrapper.eq("status", 1);
        wrapper.orderByAsc("sort");
        List<VbenMenuEntity> menuList = vbenMenuMapper.selectList(wrapper);
        // 构建树形结构
        List<VbenMenuSlideBO> treeMenu = buildMenuTree(menuList);

        List<Map<String, Object>> list = convertToMenuMap(treeMenu);

        return list;
    }

    //测试
    public List<Map<String, Object>> convertToMenuMap() {
        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, Object> menuMap = new HashMap<>();

        // 设置基本属性
        menuMap.put("name", "Dashboard");
        menuMap.put("path", "/");
        menuMap.put("redirect", "/analytics");

        // 设置meta信息
        Map<String, Object> meta = new HashMap<>();
        meta.put("title", "www");
        meta.put("order", 1);

        menuMap.put("meta", meta);

        Map<String, Object> menuMap1 = new HashMap<>();

        // 设置基本属性
        menuMap1.put("name", "analytics");
        menuMap1.put("path", "/analytics");

        menuMap1.put("component", "/dashboard/analytics/index");

        // 设置meta信息
        Map<String, Object> meta1 = new HashMap<>();
        meta1.put("title", "www");
        meta1.put("order", 1);

        menuMap1.put("meta", meta1);
        menuMap.put("children", menuMap1);

        list.add(menuMap);
        return list;
    }

    private List<VbenMenuSlideBO> buildMenuTree(List<VbenMenuEntity> menuList) {
        List<VbenMenuSlideBO> slideBOList = menuList.stream()
                .map(entity -> {
                    VbenMenuSlideBO slideBO = new VbenMenuSlideBO();

                    BeanUtils.copyProperties(entity, slideBO);
                    slideBO.setSort(entity.getSort());
                    slideBO.setId(entity.getId());
                    return slideBO;
                })
                .collect(Collectors.toList());
        System.out.println(slideBOList);

        // 1. 创建ID到节点的映射
        Map<Long, VbenMenuSlideBO> nodeMap = new HashMap<>();
        for (VbenMenuSlideBO node : slideBOList) {
            nodeMap.put(node.getId(), node);
        }
        // 2. 构建树形结构
        for (VbenMenuSlideBO node : slideBOList) {
            Long parentId = node.getParentId();
            if (!parentId.equals(ROOT_PARENT_ID)) {
                System.out.println("--------------------1111:"+parentId);
                VbenMenuSlideBO parent = nodeMap.get(parentId);
                System.out.println("--------------------1222:"+parent);
                if (parent != null) {
                    System.out.println("--------------------333:"+parent.toString());
                    parent.getChildren().add(node);  // 挂载到父节点
                }
            }
        }
        // 3. 获取根节点
        List<VbenMenuSlideBO> rootNodes = new ArrayList<>();
        for (VbenMenuSlideBO menu : slideBOList) {
            if (menu.getParentId().equals(ROOT_PARENT_ID)) {
                rootNodes.add(menu);
            }
        }
        return rootNodes;
    }

    private List<Map<String, Object>> convertToMenuMap(List<VbenMenuSlideBO> menuTree) {
        List<Map<String, Object>> result = new ArrayList<>();

        for (VbenMenuSlideBO menu : menuTree) {
            Map<String, Object> menuMap = new HashMap<>();

            // 设置基本属性
            menuMap.put("name", menu.getName());
            menuMap.put("path", menu.getPath());
            menuMap.put("redirect", menu.getRedirect());
            menuMap.put("parentId", menu.getParentId());
            menuMap.put("id", menu.getId());
            menuMap.put("type", menu.getType());
            menuMap.put("authCode", menu.getAuthCode());
            menuMap.put("component", menu.getComponent());
            menuMap.put("status", menu.getStatus());


            // 设置meta信息
            Map<String, Object> meta = new HashMap<>();
            meta.put("icon", menu.getIcon());
            meta.put("title", menu.getTitle());
//            meta.put("badgeType", menu.getBadgeType());
//            meta.put("badgeVariants", menu.getBadgeVariants());
            meta.put("order", menu.getSort());

            menuMap.put("meta", meta);

            // 处理子菜单
            if (CollUtil.isNotEmpty(menu.getChildren())) {
                List<Map<String, Object>> children = convertToMenuMap(menu.getChildren());
                menuMap.put("children", children);
            }

            result.add(menuMap);
        }

        return result;
    }


    public List<Map<String, Object>> menuList() {
        QueryWrapper<VbenMenuEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("status", 1);
        List<VbenMenuEntity> menuList = vbenMenuMapper.selectList(wrapper);
        // 构建树形结构
        List<VbenMenuSlideBO> treeMenu = buildMenuTree(menuList);

        List<Map<String, Object>> list = convertToMenuMap(treeMenu);

        return list;
    }
}
